import { join, resolve, dirname } from 'node:path';
import { createRequire } from 'node:module';
import { writeFileSync, existsSync, readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { log } from './utils';
import ejs from 'ejs';
import PageGenerator from './core/page-generator';
import type { SourceCode, SchemaNodeType, ConfigType } from '../src/types';

const _require = createRequire(import.meta.url);
const _dirname = dirname(fileURLToPath(import.meta.url));
/**
 * 配置文件
 */
// @ts-ignore;
// const defineConfigFilePath = resolve(global.__stsc_config_path);
/**
 * 模板目录
 */
const templatesPath = resolve(_dirname, 'templates');
/**
 * 源码目录
 */
const sourceCodePath = resolve(_dirname, '.source-code');
/**
 * 生成组件源码文件
 */

const renderComponent = (sourceCode: SourceCode[]) => {
  ejs.renderFile(join(templatesPath, 'source-code.ejs'), { data: sourceCode[0] }, (err, str) => {
    if (err) {
      log.error('渲染组件模板异常', err.message);
      throw err.message;
    }
    writeFileSync(join(sourceCodePath, 'component.tsx'), str);
  });
};
/**
 * 生成状态管理源码文件
 */
const renderState = (sourceCode: SourceCode[]) => {
  const { state } = sourceCode[0];
  if (state) {
    ejs.renderFile(join(templatesPath, 'use-internal-reducer.ejs'), { state }, (err, str) => {
      if (err) {
        log.error('渲染状态管理模板异常', err.message);
        throw err.message;
      }
      writeFileSync(join(sourceCodePath, 'use-internal-reducer.ts'), str);
    });
  }
};
/**
 * 编译
 */
export const compiler = async (schemas?: SchemaNodeType[]) => {
  if (!Array.isArray(schemas) || !schemas.length) {
    return;
  }
  const [schema] = schemas;
  const sourceCodeMap: SourceCode[] = [];
  if (schema.componentName === 'Page') {
    const pageGenerator = new PageGenerator({ schema });
    sourceCodeMap.push(await pageGenerator.compiler());
  }
  return sourceCodeMap;
};

const prepare = async () => {
  // @ts-ignore
  const defineConfigFilePath = resolve(global.__stsc_config_path);
  if (!existsSync(defineConfigFilePath)) {
    throw new Error('没有找到配置文件');
  }

  const res = _require(defineConfigFilePath) || {};
  const defineConfig = res.default as ConfigType;

  if (!existsSync(defineConfig?.schemaFilePath)) {
    throw new Error('没有配置schema文件路径');
  }
  const schema = readFileSync(defineConfig.schemaFilePath, {
    encoding: 'utf-8',
  });
  return schema ? JSON.parse(schema) : undefined;
};

export const start = async () => {
  try {
    const schema = await prepare();
    const sourceCode = (await compiler(schema)) || [];
    renderComponent(sourceCode);
    renderState(sourceCode);
  } catch (e: any) {
    log.error('解析异常', e.message);
    process.exit(1);
  }
};
